<template>
  <div class="tree-select-main">
    <div class="input-main" ref="inputRef">
      <div v-if="showSearch" class="select-layout">
        <input
          type="text"
          :placeholder="placeholder"
          v-model="state.current"
          @input="inputSearch"
        />
      </div>
      <div v-else class="select-layout" @click="state.isShow = !state.isShow">
        <p>{{ state.current }}</p>
        <div v-if="showIcon" class="icon-triangle" :class="{ 'icon-open': state.isShow }"></div>
      </div>
    </div>

    <transition name="drop">
      <div class="tree-main" ref="treeRef" v-if="state.isShow">
        <Tree
          :tree-options="treeSelectData"
          :is-accordion="isAccordion"
          type="menu"
          @click-item="clickItem"
        />
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { TreeOption } from '@/components/Tree.vue'

export interface TreeSelectOption extends TreeOption {}

interface Props {
  treeSelectData: Array<TreeSelectOption>
  modelValue?: string | number
  placeholder?: string
  isAccordion?: boolean
  showSearch?: boolean
  showIcon?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  treeSelectData: () => [],
  modelValue: '',
  placeholder: '请选择',
  isAccordion: false,
  showSearch: false,
  showIcon: false
})

const emit = defineEmits(['update:modelValue', 'selectItem', 'input'])

const state = ref({
  current: props.treeSelectData.find((i) => i.key === props.modelValue)?.label ?? '',
  isShow: false
})

const treeRef = ref()
const inputRef = ref()

const clickItem = (item: TreeSelectOption) => {
  state.value.current = item.label
  state.value.isShow = false

  emit('update:modelValue', item.key)
  emit('selectItem', item)
}

const inputSearch = () => {
  state.value.isShow = !!state.value.current
  emit('input', state.value.current)
}

const handleClickOutside = (e: any) => {
  if (treeRef.value && !treeRef.value.contains(e.target) && !inputRef.value?.contains(e.target)) {
    state.value.isShow = false
  }
}

onMounted(() => {
  window.addEventListener('click', handleClickOutside)
})

onBeforeUnmount(() => {
  window.removeEventListener('click', handleClickOutside)
})
</script>

<style scoped lang="scss">
.tree-select-main {
  width: 210px;
  position: relative;

  .input-main {
    display: flex;
    background: #fff;
    border-radius: 6px;
    width: inherit;
    height: 36px;
    border: 1px solid #d9d9d9;

    .select-layout {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-left: 10px;
      font-size: 14px;
      min-width: 180px;

      input {
        inset-inline: none;
        border: none;
        outline: none;
        display: block;
        padding: 0;
        height: 18px;
        width: 170px;
        font-size: 14px;

        &::-webkit-input-placeholder {
          line-height: normal;
          font-size: 12px;
        }

        &::ms-input-placeholder {
          line-height: normal;
          font-size: 12px;
        }
      }

      .icon-triangle {
        width: 6px;
        height: 6px;
        border-top: 3px solid transparent;
        border-left: 3px solid transparent;
        border-right: 3px solid #2c2d30;
        border-bottom: 3px solid #2c2d30;
        transform: rotate(-45deg);
        transition: 0.4s;
      }

      .icon-open {
        transform: rotate(45deg);
      }
    }
  }

  .tree-main {
    width: inherit;
    overflow: hidden;
    transform: rotate(0deg);
    max-height: 210px;
    position: absolute;
    background: #fff;
    box-shadow: 0 2px 10px 0 #c5c9cf80;
    overflow-y: scroll;
    padding: 6px 0;
    margin-top: 8px;

    &::-webkit-scrollbar {
      width: 5px;
    }

    &::-webkit-scrollbar-track {
      background: #fff;
      border-radius: 2px;
    }

    &::-webkit-scrollbar-thumb {
      background: #d9dce3;
      border-radius: 2px;
    }
  }
}

.drop-enter-active {
  animation: drop-anim 0.4s;
}

.drop-leave-active {
  animation: drop-anim 0.4s reverse;
}

@keyframes drop-anim {
  from {
    transform: translateY(-20px);
    opacity: 0;
  }
}
</style>
